package com.ym.core.es.query;

import cn.hutool.core.util.ReflectUtil;
import com.ym.core.es.annotation.HeightWord;
import com.ym.core.es.domain.bo.HeightWordTags;
import com.ym.core.es.domain.index.BaseIdIndex;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class QueryParser {

	NativeSearchQueryBuilder nativeSearchQueryBuilder;

	public <T extends BaseIdIndex> QueryParser(Class<T> indexClass) {
		nativeSearchQueryBuilder = new NativeSearchQueryBuilder();

		// 高亮词设置
		Map<String, HeightWord> heightWordField = getHeightWordField(indexClass);
		List<HighlightBuilder.Field> heighLight = new ArrayList<>();
		heightWordField.forEach((key, value) -> {
			HighlightBuilder.Field field = new HighlightBuilder.Field(key);
			HeightWordTags tags = value.tags();
			field.preTags(tags.getPreTag()).postTags(tags.getPostTag()).fragmentOffset(value.highlightNum());
			heighLight.add(field);
		});
		nativeSearchQueryBuilder.withHighlightFields(heighLight.toArray(new HighlightBuilder.Field[heighLight.size()]));
	}

	public NativeSearchQuery build() {
		return nativeSearchQueryBuilder.build();
	}

	/**
	 * 查询
	 *
	 * @param queryBuilder 查询条件
	 * @return
	 */
	public QueryParser query(QueryBuilder queryBuilder) {
		query(queryBuilder, null, null);
		return this;
	}

	/**
	 * 查询
	 *
	 * @param queryBuilder 查询条件
	 * @param includeField 查询指定字段
	 * @return
	 */
	public QueryParser query(QueryBuilder queryBuilder, String[] includeField) {
		return query(queryBuilder, includeField, null);
	}

	/**
	 * 查询
	 *
	 * @param queryBuilder 条件
	 * @param limit        指定条数
	 * @return
	 */
	public QueryParser query(QueryBuilder queryBuilder, Integer limit) {
		return query(queryBuilder, null, limit);
	}

	/**
	 * 查询
	 *
	 * @param queryBuilder 条件
	 * @param includeField 指定字段
	 * @param limit        指定条数
	 * @return
	 */
	public QueryParser query(QueryBuilder queryBuilder, String[] includeField, Integer limit) {
		nativeSearchQueryBuilder.withQuery(queryBuilder);
		if (includeField != null) {
			FetchSourceFilter filter = new FetchSourceFilter(includeField, null);
			nativeSearchQueryBuilder.withSourceFilter(filter);
		}
		if (limit != null) {
			nativeSearchQueryBuilder.withPageable(PageRequest.of(0, limit));
		}
		return this;
	}

	/**
	 * 分页查询
	 *
	 * @param queryBuilder 条件
	 * @param page         分页参数
	 * @param sortBuilder  排序
	 * @return
	 */
	public QueryParser page(QueryBuilder queryBuilder, PageRequest page, SortBuilder sortBuilder) {
		nativeSearchQueryBuilder.withQuery(queryBuilder);
		nativeSearchQueryBuilder.withPageable(page);
		if (sortBuilder != null) {
			nativeSearchQueryBuilder.withSort(sortBuilder);
		}
		return this;
	}


	/**
	 * 获取高亮注解
	 *
	 * @param indexClass
	 * @param <T>
	 * @return
	 */
	private <T extends BaseIdIndex> Map<String, HeightWord> getHeightWordField(Class<T> indexClass) {
		Map<String, HeightWord> map = new HashMap<>();
		Field[] fields = ReflectUtil.getFields(indexClass);
		for (Field field : fields) {
			HeightWord heightWord = field.getAnnotation(HeightWord.class);
			if (heightWord != null) {
				map.put(field.getName(), heightWord);
			}
		}
		return map;
	}


}
